Move to new model of network and vif control using shell scripts.
401d7e160vaxMBAUSLSicuZ7AQjJ3w tools/examples/Makefile
401d7e16UgeqroJQTIhwkrDVkoWgZQ tools/examples/README
405ff55dawQyCHFEnJ067ChPRoXBBA tools/examples/init.d/xend
+40ee75a9xFz6S05sDKu-JCLqyVTkDA tools/examples/network
+40ee75a967sxgcRY4Q7zXoVUaJ4flA tools/examples/vif-bridge
40e15b7edWEtBf_oe3eBwGKuh1dyzQ tools/examples/vifctl
+40ee75a93cqxHp6MiYXxxwR5j2_8QQ tools/examples/xend-config.sxp
40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmdefaults
40dfd40auJwNnb8NoiSnRkvZaaXkUg tools/examples/xmnetbsd
3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxc/Makefile
INSTALL = $(wildcard *.py)
-ETC = xmdefaults
-ETCDIR = /etc/xen
-
INITD = init.d/xend
-XEND = vifctl
-XEND_DIR = $(ETCDIR)/xend
+XEN_CONFIG_DIR = /etc/xen
+XEN_CONFIGS = xmdefaults xmnetbsd xend-config.sxp
+
+XEN_SCRIPT_DIR = /etc/xen
+XEN_SCRIPTS = vifctl network vif-bridge
all:
-install: all install-initd install-etc install-xend
+install: all install-initd install-configs install-scripts
install-initd:
mkdir -p $(prefix)/etc/init.d
install -m0755 $(INITD) $(prefix)/etc/init.d
-install-etc:
- mkdir -p $(prefix)$(ETCDIR)
- mkdir -p $(prefix)$(ETCDIR)/auto
- for i in $(ETC); \
- do [ -a $(prefix)/$(ETCDIR)/$$i ] || \
- install -m0644 $$i $(prefix)$(ETCDIR); \
+install-configs:
+ mkdir -p $(prefix)$(XEN_CONFIG_DIR)
+ mkdir -p $(prefix)$(XEN_CONFIG_DIR)/auto
+ for i in $(XEN_CONFIGS); \
+ do [ -a $(prefix)/$(XEN_CONFIG_DIR)/$$i ] || \
+ install -m0644 $$i $(prefix)$(XEN_CONFIG_DIR); \
done
-install-xend:
- mkdir -p $(prefix)$(XEND_DIR)
- for i in $(XEND); \
- do [ -a $(prefix)/$(XEND_DIR)/$$i ] || \
- install -m0755 $$i $(prefix)$(XEND_DIR); \
+install-scripts:
+ mkdir -p $(prefix)$(XEN_SCRIPT_DIR)
+ for i in $(XEN_SCRIPTS); \
+ do [ -a $(prefix)/$()/$$i ] || \
+ install -m0755 $$i $(prefix)$(XEN_SCRIPT_DIR); \
done
clean:
--- /dev/null
+#!/bin/sh
+#============================================================================
+# Example Xen network start/stop script.
+# Xend calls a network script when it starts.
+# This is the default script.
+#
+# /etc/xen/network (start|stop|status) {VAR=VAL}*
+#
+# Vars:
+#
+# bridge The bridge to use (default xen-br0).
+# netdev The interface to add to the bridge (default eth0).
+# antispoof Whether to use iptables to prevent spoofing (default yes).
+#
+# start:
+# Creates the bridge and enslaves netdev to it.
+# Copies the IP addresses from netdev to the bridge.
+# Deletes the routes to netdev and adds them on bridge.
+#
+# stop:
+# Removes netdev from the bridge.
+# Deletes the routes to bridge and adds them to netdev.
+#
+# status:
+# Print ifconfig for netdev and bridge.
+# Print routes.
+#
+#============================================================================
+
+# Exit if anything goes wrong.
+set -e
+
+# First arg is the operation.
+OP=$1
+shift
+
+# Pull variables in args in to environment.
+for arg ; do export "${arg}" ; done
+
+bridge=${bridge:-xen-br0}
+netdev=${netdev:-eth0}
+antispoof=${antispoof:-yes}
+
+echo "network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof"
+
+# Usage: transfer_addrs src dst
+# Copy all IP addresses (including aliases) from device $src to device $dst.
+transfer_addrs () {
+ local src=$1
+ local dst=$2
+ # Don't bother if $dst already has IP addresses.
+ if ip addr show dev ${dst} | egrep -q '^ *inet' ; then
+ return
+ fi
+ # Address lines start with 'inet' and have the device in them.
+ # Replace 'inet' with 'ip addr add' and change the device name $src
+ # to 'dev $src'.
+ ip addr show dev ${src} | egrep '^ *inet' | sed -e "
+s/inet/ip addr add/
+s/${src}/dev ${dst}/
+" | sh -e
+}
+
+# Usage: transfer_routes src dst
+# Get all IP routes to device $src, delete them, and
+# add the same routes to device $dst.
+# The original routes have to be deleted, otherwise adding them
+# for $dst fails (duplicate routes).
+transfer_routes () {
+ local src=$1
+ local dst=$2
+ # List all routes and grep the ones with $src in.
+ # Stick 'ip route del' on the front to delete.
+ # Change $src to $dst and use 'ip route add' to add.
+ ip route list | grep ${src} | sed -e "
+h
+s/^/ip route del /
+P
+g
+s/${src}/${dst}/
+s/^/ip route add /
+P
+d
+" | sh -e
+}
+
+# Usage: create_bridge dev bridge
+# Create bridge $bridge and add device $dev to it.
+create_bridge () {
+ local dev=$1
+ local bridge=$2
+
+ # Don't create the bridge if it already exists.
+ if ! brctl show | grep -q ${bridge} ; then
+ brctl addbr ${bridge}
+ brctl stp ${bridge} off
+ brctl setfd ${bridge} 0
+ brctl sethello ${bridge} 0
+ fi
+ ifconfig ${bridge} up
+ # Don't add $dev to $bridge if it's already on a bridge.
+ if ! brctl show | grep -q ${dev} ; then
+ brctl addif ${bridge} ${dev}
+ fi
+}
+
+# Usage: antispoofing dev bridge
+# Set the default forwarding policy for $dev to drop.
+# Allow forwarding to the bridge.
+antispoofing () {
+ local dev=$1
+ local bridge=$2
+
+ iptables -P FORWARD DROP
+ iptables -A FORWARD -m physdev --physdev-in ${dev} -j ACCEPT
+}
+
+# Usage: show_status dev bridge
+# Print ifconfig and routes.
+show_status () {
+ local dev=$1
+ local bridge=$2
+
+ echo '============================================================'
+ ifconfig ${dev}
+ ifconfig ${bridge}
+ echo ' '
+ ip route list
+ echo ' '
+ route -n
+ echo '============================================================'
+}
+
+case ${OP} in
+ start)
+ # Create the bridge and give it the interface IP addresses.
+ # Move the interface routes onto the bridge.
+ create_bridge ${netdev} ${bridge}
+ transfer_addrs ${netdev} ${bridge}
+ transfer_routes ${netdev} ${bridge}
+
+ if [ ${antispoof} == 'yes' ] ; then
+ antispoofing ${netdev} ${bridge}
+ fi
+
+ ;;
+
+ stop)
+ # Remove the interface from the bridge.
+ # Move the routes back to the interface.
+ brctl delif ${bridge} ${netdev}
+ transfer_routes ${bridge} ${netdev}
+
+ # It's not our place to be enabling forwarding...
+ ;;
+
+ status)
+ show_status ${netdev} ${bridge}
+ ;;
+
+ *)
+ echo 'Unknown command: ' ${OP}
+ echo 'Valid commands are: start, stop, status'
+ exit 1
+esac
--- /dev/null
+#!/bin/sh
+#============================================================================
+# /etc/xen/vif-bridge
+#
+# Script for configuring a vif in bridged mode.
+# Xend calls a vif script when bringing a vif up or down.
+# This script is the default - but it can be configured for each vif.
+#
+# Example invocation:
+#
+# vif-bridge up domain=VM1 vif=vif1.0 bridge=xen-br0 ip="128.232.38.45/28 10.10.10.55/24"
+#
+#
+# Usage:
+# vif-bridge (up|down) {VAR=VAL}*
+#
+# Vars:
+#
+# domain name of the domain the interface is on (required).
+# vif vif interface name (required).
+# mac vif MAC address (required).
+# bridge bridge to add the vif to (required).
+# ip list of IP networks for the vif, space-separated (optional).
+#
+# up:
+# Enslaves the vif interface to the bridge and adds iptables rules
+# for its ip addresses (if any).
+#
+# down:
+# Removes the vif interface from the bridge and removes the iptables
+# rules for its ip addresses (if any).
+#============================================================================
+
+# Exit if anything goes wrong
+set -e
+
+echo "vif-bridge $*"
+
+# Operation name.
+OP=$1
+shift
+
+# Pull variables in args into environment
+for arg ; do export "${arg}" ; done
+
+# Required parameters. Fail if not set.
+domain=${domain:?}
+vif=${vif:?}
+mac=${mac:?}
+bridge=${bridge:?}
+
+# Optional parameters. Set defaults.
+ip=${ip:-''} # default to null (do nothing)
+
+# Are we going up or down?
+case $OP in
+ up)
+ brcmd='addif'
+ iptcmd='-A'
+ ;;
+ down)
+ brcmd='delif'
+ iptcmd='-D'
+ ;;
+ *)
+ echo 'Invalid command: ' $OP
+ echo 'Valid commands are: up, down'
+ exit 1
+ ;;
+esac
+
+# Add/remove vif to/from bridge.
+brctl ${brcmd} ${bridge} ${vif}
+
+if [ ${ip} ] ; then
+
+ # If we've been given a list of IP networks, allow pkts with these src addrs.
+ for addr in ${ip} ; do
+ iptables ${iptcmd} FORWARD -m physdev --physdev-in ${vif} -s ${addr} -j ACCEPT
+ done
+
+ # Always allow us to talk to a DHCP server anyhow.
+ iptables ${iptcmd} FORWARD -m physdev --physdev-in ${vif} -p udp --sport 68 --dport 67 -j ACCEPT
+fi
+
# added on up and removed on down. The bridge a vif is added to can
# be set in the vm config.
#
-# The default bridge is nbe-br.
+# The default bridge is xen-br0.
# The default interface is eth0.
#
#============================================================================
prefix = 'vifctl_'
- DEFAULT_BRIDGE = 'nbe-br'
+ DEFAULT_BRIDGE = 'xen-br0'
DEFAULT_INTERFACE = 'eth0'
def __init__(self):
--- /dev/null
+# Xend configuration file.
+
+# Port xend should use for the HTTP interface.
+(xend-port 8000)
+
+# Address xend should listen on.
+# Specifying 'localhost' prevents remote connections.
+# Specifying the empty string '' allows all connections.
+(xend-address '')
+
+# The script used to start/stop networking for xend.
+(network-script network)
+
+# The default bridge that virtual interfaces should be connected to.
+(vif-bridge xen-br0)
+
+# The default script used to control virtual interfaces.
+(vif-script vif-bridge)
+
+# Whether iptables should be set up to prevent IP spoofing for
+# virtual interfaces. Specify 'yes' or 'no'.
+(vif-antispoof no)
+
# Optionally define mac and/or bridge for the network interfaces.
# Random MACs are assigned if not given.
-#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
+#vif = [ 'mac=aa:00:00:00:00:11, bridge=xen-br0' ]
#----------------------------------------------------------------------------
# Define the disk devices you want the domain to have access to, and
# Optionally define mac and/or bridge for the network interfaces.
# Random MACs are assigned if not given.
-#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
+#vif = [ 'mac=aa:00:00:00:00:11, bridge=xen-br0' ]
# Specify IP address(es), for the new domain. You need to
# configure IP addrs within the domain just as you do normally. This
#============================================================================
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
#============================================================================
-# Move the IP address from eth0 onto the Xen bridge (nbe-br).
+# Move the IP address from eth0 onto the Xen bridge (xen-br0).
# Only works if the bridge control utils (brctl) have been installed.
#============================================================================
long_options = ['help', 'verbose', 'quiet',
'interface=', 'bridge=', 'create']
+defaults['interface'] = 'eth0'
+defaults['bridge'] = 'xen-br0'
+
def usage():
print """Usage:
%s [options]
When bridging is used, eth0 may not have an IP address,
as it may have been moved onto the bridge.
"""
-NBE_BRIDGE = 'nbe-br'
+NBE_BRIDGE = 'xen-br0'
def get_current_ipaddr(dev='eth0'):
"""Get the primary IP address for the given network interface.
-"""Xend interface to the vifctl script.
+"""Xend interface to networking control scripts.
"""
import os
import os.path
import sys
-VIFCTL = '/etc/xen/xend/vifctl'
+from xen.xend import XendRoot
+xroot = XendRoot.instance()
-def init():
- """Call 'vifctl init'. Called when xend starts.
+"""Where network control scripts live."""
+SCRIPT_DIR = xroot.network_script_dir
+
+def network(op, script=None, bridge=None, antispoof=None):
+ """Call a network control script.
+ Xend calls this with op 'start' when it starts.
+
+ @param op: operation (start, stop, status)
+ @param script: network script name
+ @param bridge: xen bridge
+ @param antispoof: whether to enable IP antispoofing rules
"""
- os.system(VIFCTL + ' init ')
+ if op not in ['start', 'stop', 'status']:
+ raise ValueError('Invalid operation:' + op)
+ if script is None:
+ script = xroot.get_network_script()
+ if bridge is None:
+ bridge = xroot.get_vif_bridge()
+ if antispoof is None:
+ antispoof = xroot.get_vif_antispoof()
+ script = os.path.join(SCRIPT_DIR, script)
+ args = [op]
+ args.append("bridge='%s'" % bridge)
+ if antispoof:
+ args.append("antispoof=yes")
+ else:
+ args.append("antispoof=no")
+ args = ' '.join(args)
+ os.system(script + ' ' + args)
+
+def vifctl(op, vif=None, script=None, domain=None, mac=None, bridge=None, ipaddr=[]):
+ """Call a vif control script.
+ Xend calls this when bringing vifs up or down.
-def vifctl_args(vif, mac=None, bridge=None, ipaddr=[]):
- """Construct the argument list for vifctl.
+ @param op: vif operation (up, down)
+ @param vif: vif name
+ @param script: name of control script
+ @param domain: name of domain the vif is on
+ @param mac: vif MAC address
+ @param bridge: bridge to add the vif to
+ @param ipaddr: list of ipaddrs the vif may use
"""
- args = ['vif=%s' % vif]
- if mac:
- args.append('mac=%s' % mac)
+ if op not in ['up', 'down']:
+ raise ValueError('Invalid operation:' + op)
+ if script is None:
+ script = xroot.get_vif_script()
+ if bridge is None:
+ bridge = xroot.get_vif_bridge()
+ script = os.path.join(SCRIPT_DIR, script)
+ args = [op]
+ args.append("vif='%s'" % vif)
+ args.append("domain='%s'" % domain)
+ args.append("mac='%s'" % mac)
if bridge:
- args.append('bridge=%s' % bridge)
- for ip in ipaddr:
- args.append('ipaddr=%s' % ip)
- return ' '.join(args)
-
-def up(vif, **kwds):
- """Call 'vifctl up' for a vif. Called when a vif is created.
- """
- args = vifctl_args(vif, **kwds)
- os.system(VIFCTL + ' up ' + args)
+ args.append("bridge='%s'" % bridge)
+ if ipaddr:
+ ips = ' '.join(ipaddr)
+ args.append("ip='%s'" % ips)
+ args = ' '.join(args)
+ os.system(script + ' ' + args)
-def down(vif, **kwds):
- """Call 'vifctl down' for a vif. Called when a vif is destroyed.
- """
- args = vifctl_args(vif, **kwds)
- os.system(VIFCTL + ' down ' + args)
ctrl.addCallback(fn)
return ctrl
-def make_vif(dom, vif, vmac, recreate=0):
- """Create a virtual network device for a domain.
-
-
- @returns Deferred
- """
- xend.netif_create(dom, recreate=recreate)
- d = xend.netif_dev_create(dom, vif, vmac, recreate=recreate)
- return d
-
def vif_up(iplist):
"""send an unsolicited ARP reply for all non link-local IP addresses.
def _vm_configure1(val, vm):
d = vm.create_devices()
- print '_vm_configure1> made devices...'
+ #print '_vm_configure1> made devices...'
def cbok(x):
- print '_vm_configure1> cbok', x
+ #print '_vm_configure1> cbok', x
return x
d.addCallback(cbok)
d.addCallback(_vm_configure2, vm)
- print '_vm_configure1<'
+ #print '_vm_configure1<'
return d
def _vm_configure2(val, vm):
- print '>callback _vm_configure2...'
+ #print '>callback _vm_configure2...'
d = vm.configure_fields()
def cbok(results):
- print '_vm_configure2> cbok', results
+ #print '_vm_configure2> cbok', results
return vm
def cberr(err):
- print '_vm_configure2> cberr', err
+ #print '_vm_configure2> cberr', err
vm.destroy()
return err
d.addCallback(cbok)
d.addErrback(cberr)
- print '<_vm_configure2'
+ #print '<_vm_configure2'
return d
class XendDomainInfo:
raise VmError('vif: vif in netif backend domain')
vif = index #todo
vmac = sxp.child_value(val, "mac")
- defer = make_vif(vm.dom, vif, vmac, vm.recreate)
+ xend.netif_create(vm.dom, recreate=vm.recreate)
+ defer = xend.netif_dev_create(vm.dom, vif, val, recreate=vm.recreate)
def fn(id):
dev = xend.netif_dev(vm.dom, vif)
- devid = sxp.attribute(val, 'id')
- if devid:
- dev.setprop('id', devid)
- bridge = sxp.child_value(val, "bridge")
- dev.up(bridge)
+ dev.vifctl('up')
vm.add_device('vif', dev)
print 'vm_dev_vif> created', dev
return id
"""Environment variable used to override config_default."""
config_var = "XEND_CONFIG"
+ """Where network control scripts live."""
+ network_script_dir = "/etc/xen"
+
def __init__(self):
self.rebooted = 0
self.last_reboot = None
return self.rebooted
def configure(self):
+ print 'XendRoot>configure>'
self.set_config()
self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
self.lastboot = self.get_config_value("lastboot", self.lastboot_default)
The config file is a sequence of sxp forms.
"""
self.config_path = os.getenv(self.config_var, self.config_default)
+ print 'XendRoot>set_config> config_path=', self.config_path
if os.path.exists(self.config_path):
+ print 'XendRoot>set_config> loading'
fin = file(self.config_path, 'rb')
try:
config = sxp.parse(fin)
- config.insert(0, 'config')
+ config.insert(0, 'xend-config')
self.config = config
finally:
fin.close()
else:
- self.config = ['config']
+ print 'XendRoot>set_config> not found'
+ self.config = ['xend-config']
+ print 'XendRoot> config=', self.config
def get_config(self, name=None):
"""Get the configuration element with the given name, or
the whole configuration if no name is given.
- name element name (optional)
- returns config or none
+ @param name: element name (optional)
+ @return: config or none
"""
if name is None:
val = self.config
def get_config_value(self, name, val=None):
"""Get the value of an atomic configuration element.
- name element name
- val default value (optional, defaults to None)
- returns value
+ @param name: element name
+ @param val: default value (optional, defaults to None)
+ @return: value
"""
return sxp.child_value(self.config, name, val=val)
+ def get_xend_port(self):
+ return int(self.get_config_value('xend-port', '8000'))
+
+ def get_xend_address(self):
+ return self.get_config_value('xend-address', '')
+
+ def get_network_script(self):
+ return self.get_config_value('network-script', 'network')
+
+ def get_vif_bridge(self):
+ return self.get_config_value('vif-bridge', 'xen-br0')
+
+ def get_vif_script(self):
+ return self.get_config_value('vif-script', 'vif-bridge')
+
+ def get_vif_antispoof(self):
+ v = self.get_config_value('vif-antispoof', 'yes')
+ return v in ['yes', '1', 'on']
+
def instance():
global inst
try:
def netif_get(self, dom):
return self.netifCF.getInstanceByDom(dom)
- def netif_dev_create(self, dom, vif, vmac, recreate=0):
+ def netif_dev_create(self, dom, vif, config, recreate=0):
"""Create a network device.
- todo
"""
ctrl = self.netifCF.getInstanceByDom(dom)
if not ctrl:
raise ValueError('No netif controller: %d' % dom)
- d = ctrl.attachDevice(vif, vmac, recreate=recreate)
+ d = ctrl.attachDevice(vif, config, recreate=recreate)
return d
def netif_dev(self, dom, vif):
from SrvRoot import SrvRoot
def create(port=None, interface=None, bridge=0):
- if port is None: port = 8000
- if interface is None: interface = ''
+ if port is None:
+ port = xroot.get_xend_port()
+ if interface is None:
+ interface = xroot.get_xend_address()
if bridge or xroot.rebooted:
- init_bridge()
+ Vifctl.network('start')
root = resource.Resource()
xend = SrvRoot()
root.putChild('xend', xend)
site = server.Site(root)
reactor.listenTCP(port, site, interface=interface)
-def init_bridge():
- Vifctl.init()
-
def main(port=None, interface=None):
create(port, interface)
reactor.run()
"""Info record for a network device.
"""
- def __init__(self, ctrl, vif, mac):
+ def __init__(self, ctrl, vif, config):
controller.Dev.__init__(self, ctrl)
self.vif = vif
- self.mac = mac
self.evtchn = None
+ self.configure(config)
+
+ def configure(self, config):
+ self.config = config
+ self.mac = None
self.bridge = None
- self.ipaddr = []
+ self.script = None
+ self.ipaddr = None
+
+ vmac = sxp.child_value(config, 'mac')
+ if not vmac: raise ValueError("invalid mac")
+ mac = [ int(x, 16) for x in vmac.split(':') ]
+ if len(mac) != 6: raise ValueError("invalid mac")
+ self.mac = mac
+ self.bridge = sxp.child_value(config, 'bridge')
+ self.script = sxp.child_value(config, 'script')
+
+ ipaddrs = sxp.children(config, elt='ip')
+ for ipaddr in ipaddrs:
+ self.ipaddr.append(sxp.child0(ipaddr))
+
def sxpr(self):
vif = str(self.vif)
mac = self.get_mac()
- val = ['netdev', ['vif', vif], ['mac', mac]]
+ val = ['vif', ['idx', vif], ['mac', mac]]
if self.bridge:
val.append(['bridge', self.bridge])
+ if self.script:
+ val.append(['script', self.script])
+ for ip in self.ipaddr:
+ val.append(['ip', ip])
if self.evtchn:
val.append(['evtchn',
self.evtchn['port1'],
return ':'.join(map(lambda x: "%x" % x, self.mac))
def vifctl_params(self):
- return { 'mac' : self.get_mac(),
+ from xen.xend import XendDomain
+ xd = XendDomain.instance()
+ dom = self.controller.dom
+ dominfo = xd.domain_get(dom)
+ name = (dominfo and dominfo.name) or ('DOM%d' % dom)
+ return { 'domain': name,
+ 'vif' : self.get_vifname(),
+ 'mac' : self.get_mac(),
'bridge': self.bridge,
- 'ipaddr': self.ipaddr }
+ 'script': self.script,
+ 'ipaddr': self.ipaddr, }
- def up(self, bridge=None, ipaddr=[]):
- """Bring the device up.
-
- bridge ethernet bridge to connect to
- ipaddr list of ipaddrs to filter using iptables
+ def vifctl(self, op):
+ """Bring the device up or down.
"""
- self.bridge = bridge
- self.ipaddr = ipaddr
- Vifctl.up(self.get_vifname(), **self.vifctl_params())
-
- def down(self):
- """Bring the device down.
- """
- Vifctl.down(self.get_vifname(), **self.vifctl_params())
+ Vifctl.vifctl(op, **self.vifctl_params())
def destroy(self):
"""Destroy the device's resources and disconnect from the back-end
"""
def cb_destroy(val):
self.controller.send_be_destroy(self.vif)
- self.down()
+ self.vifctl('down')
#d = self.controller.factory.addDeferred()
d = defer.Deferred()
d.addCallback(cb_destroy)
val = ['netif', ['dom', self.dom]]
return val
- def randomMAC(self):
- """Generate a random MAC address.
-
- Uses OUI (Organizationally Unique Identifier) AA:00:00, an
- unassigned one that used to belong to DEC. The OUI list is
- available at 'standards.ieee.org'.
-
- The remaining 3 fields are random, with the first bit of the first
- random field set 0.
-
- returns array of 6 ints
- """
- mac = [ 0xaa, 0x00, 0x00,
- random.randint(0x00, 0x7f),
- random.randint(0x00, 0xff),
- random.randint(0x00, 0xff) ]
- return mac
-
def lostChannel(self):
"""Method called when the channel has been lost.
"""
"""
return self.devices.get(vif)
- def addDevice(self, vif, vmac):
- """Add a network interface. If vmac is None a random MAC is
- assigned. If specified, vmac must be a string of the form
- XX:XX:XX:XX:XX where X is hex digit.
+ def addDevice(self, vif, config):
+ """Add a network interface.
vif device index
- vmac device MAC
+ config device configuration
returns device
"""
- if vmac is None:
- mac = self.randomMAC()
- else:
- mac = [ int(x, 16) for x in vmac.split(':') ]
- if len(mac) != 6: raise ValueError("invalid mac")
- dev = NetDev(self, vif, mac)
+ dev = NetDev(self, vif, config)
self.devices[vif] = dev
return dev
for dev in self.getDevices():
dev.destroy()
- def attachDevice(self, vif, vmac, recreate=0):
+ def attachDevice(self, vif, config, recreate=0):
"""Attach a network device.
If vmac is None a random mac address is assigned.
@param vif interface index
@param vmac mac address (string)
"""
- self.addDevice(vif, vmac)
+ self.addDevice(vif, config)
d = defer.Deferred()
if recreate:
d.callback(self)
"""Domain creation.
"""
+import random
import string
import sys
fn=append_value, default=[],
use="Add an IP address to the domain.")
-gopts.var('vif', val="mac=MAC,bridge=BRIDGE",
+gopts.var('vif', val="mac=MAC,bridge=BRIDGE,script=SCRIPT",
fn=append_value, default=[],
use="""Add a network interface with the given MAC address and bridge.
+ The vif is configured by calling the given configuration script.
If mac is not specified a random MAC address is used.
If bridge is not specified the default bridge is used.
+ If script is not specified the default script is used.
This option may be repeated to add more than one vif.
Specifying vifs will increase the number of interfaces as needed.
""")
config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
config_devs.append(['device', config_pci])
+def randomMAC():
+ """Generate a random MAC address.
+
+ Uses OUI (Organizationally Unique Identifier) AA:00:00, an
+ unassigned one that used to belong to DEC. The OUI list is
+ available at 'standards.ieee.org'.
+
+ The remaining 3 fields are random, with the first bit of the first
+ random field set 0.
+
+ returns array of 6 ints
+ """
+ mac = [ 0xaa, 0x00, 0x00,
+ random.randint(0x00, 0x7f),
+ random.randint(0x00, 0xff),
+ random.randint(0x00, 0xff) ]
+ return ':'.join(map(lambda x: "%x" % x, mac))
+
def configure_vifs(config_devs, vals):
"""Create the config for virtual network interfaces.
"""
d = vifs[idx]
mac = d.get('mac')
bridge = d.get('bridge')
+ script = d.get('script')
else:
- mac = None
+ mac = randomMAC()
bridge = None
+ script = None
config_vif = ['vif']
- if mac:
- config_vif.append(['mac', mac])
+ config_vif.append(['mac', mac])
if bridge:
config_vif.append(['bridge', bridge])
+ if script:
+ config_vif.append(['script', script])
config_devs.append(['device', config_vif])
def configure_vfr(config, vals):